package com.robot.topology.robot.service.solo;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.robot.topology.graph.domain.Edge;
import com.robot.topology.robot.domain.Robot;
import com.robot.topology.robot.service.RobotManagerImpl;

public class RobotSoloManagerImpl extends RobotManagerImpl {

	private Integer sizeRoutineTable;
	private Double sumWeights;

	private HashMap<Edge,Double> mapRT=null;

	public RobotSoloManagerImpl(Robot robot) {
		//Manager for the bean Robot, we make the link with the bean
		super(robot);
	}

	public void moveRobotOneStep(Integer step){
		//This method moves the robot from its current node to the next node through an edge
		// This edge is chosen in a probabilistic way

		//The random number generated to simulate the randomness of the choice
		Double aRandomNumber = Math.random();

		//We sum the weights of the outgoing edges of the same node
		//Used then to normalize the strength of each edge of the same node
		//and allow the robot to make a probabilistic choice for its next edge
		this.sumWeights =(double)0;

		//We get the routine table of the current node using the robot knowledge
		this.mapRT=robot.getCurrentVertex().getRoutineTable().getTheRoutineTable();

		//Check the size of the routine table
		this.sizeRoutineTable=this.mapRT.size();

		//Get the sum of the weight values of the edge
		for (Double value : mapRT.values()) {
			System.out.println("Values of the edges to choose from : "+value);
			sumWeights+=value;
		}
		System.out.println("Sum of the weights for computing proba: "+sumWeights);

		System.out.println("I choose a random number: "+aRandomNumber);

		//Compute the edge to follow
		chooseEdgeToFollow(step, aRandomNumber);
		System.out.println("I chose : "+this.edgeToFollow.toStringWeight());
		System.out.println("Its weight is : "+this.edgeToFollow.getWeight());


		//move to the proposed vertex
		//get the destination of the chosen edge
		this.vertexToMoveTo=this.edgeToFollow.getDestination();
		//Our robot has a new current edge
		this.robot.setCurrentVertex(this.vertexToMoveTo);
		System.out.println("I moved to "+this.robot.getCurrentVertex().toString());

		//Add the used edge to Path
		this.robot.getCurrentPath().addEdge(this.edgeToFollow);
		//Delete used edge from the unused edges Path
		this.robot.getUnusedEdges().deleteEdgeFromPath(edgeToFollow);
	}

	private void chooseEdgeToFollow(Integer step, Double aRandomNumber){
		//Iteration number
		int loopNumber=1;
		//Variable used to store the probability to choose an edge
		Double probaEdge=0.5;

		//Iterator to read through the routine table
		Iterator<Map.Entry<Edge,Double>> entries = this.mapRT.entrySet().iterator();

		//for each edge in the routine table of the current node
		while (entries.hasNext()) {

			//Get a value in the routine table, that is an edge and its associated value
			Map.Entry<Edge,Double> entry = entries.next();
			System.out.println("Computing proba :" +entry.getValue()+" / "+sumWeights);

			//We compute its associated probability: Px = Px / (Px + Py)
			probaEdge=entry.getValue()/sumWeights;
			System.out.println("Dealing with "+entry.getKey().toStringWeight());

			System.out.println("aRandomNumber "+aRandomNumber);
			System.out.println("probaEdge "+probaEdge);

			// If the routine table contains only one edge
			if (this.sizeRoutineTable==1 )
				//we choose the edge as being the one to follow
				this.edgeToFollow=entry.getKey();
			//if the routine table contains more than one edge
			else if (this.sizeRoutineTable>1 ){
				
				if (loopNumber == 1){
					//If the random number chosen is lower than the probability
					//of the current edge to be selected
					if (aRandomNumber<probaEdge){
						//We select this edge
						this.edgeToFollow=entry.getKey();
						System.out.println("Edge selected: "+entry.getKey().toStringWeight());
					}

				} else if (loopNumber == 2){
					//If the random number chosen is higher than the probability
					//of the current edge to be selected
					if (aRandomNumber>(1-probaEdge)){
						//We select this edge
						this.edgeToFollow=entry.getKey();
						System.out.println("Edge selected: "+entry.getKey().toStringWeight());
					}
				}
			}
			loopNumber++;
		}

	}
}
